package com.neural.infrastructure;

import java.util.ArrayList;
import java.util.List;

import com.neural.activation.Activation;
import com.neural.activation.ActivationManager;
import com.neural.descriptor.LayerDescriptor;
import com.neural.descriptor.NeuronDescriptor;
import com.neural.descriptor.Point;
import com.neural.descriptor.SizeDescriptor;
import com.neural.randomizer.Randomizer;

public abstract class Layer implements ILayer {

	protected final List<Neuron> neurons;
	protected final Randomizer randomizer;
	protected final Activation activationMethod;
	protected final SizeDescriptor sizeDescriptor;

	public Layer(LayerDescriptor layerDescriptor, ILayer previousLayer) {
		this.sizeDescriptor = layerDescriptor.getSizeDescriptor();
		this.randomizer = new Randomizer(layerDescriptor.getRange(), 1000);
		this.activationMethod = ActivationManager.getActivationFromName(layerDescriptor.getActivationMethod());
		this.neurons = createNeurons(layerDescriptor.getNeuronsDescriptor(), previousLayer, randomizer);
	}

	private List<Neuron> createNeurons(List<NeuronDescriptor> neuronDescriptors, ILayer previousLayer, Randomizer randomizer) {
		List<Neuron> neurons = new ArrayList<Neuron>(neuronDescriptors.size());
		int neuronNum = 0;
		for (NeuronDescriptor neuronDescriptor : neuronDescriptors) {
			Neuron neuron = new Neuron(neuronDescriptor, previousLayer, randomizer, new Point(neuronNum, sizeDescriptor));
			neurons.add(neuron);
			neuronNum++;
		}
		return neurons;
	}

	public List<Neuron> getNeurons() {
		return neurons;
	}

	public SizeDescriptor getSizeDescriptor() {
		return sizeDescriptor;
	}

	public List<Double> getValues() {

		List<Double> values = new ArrayList<Double>(neurons.size());
		for (int i = 0; i < neurons.size(); i++) {
			values.add(neurons.get(i).getValue());
		}
		return values;
	}
}
